package cn.ilikes.tools.hbase.jpa.indexs.lucenes;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumericField;
import org.slf4j.Logger;

import cn.ilikes.tools.hbase.jpa.SysConfigs;
import cn.ilikes.tools.hbase.jpa.annotations.IndexColumn.Index;
import cn.ilikes.tools.hbase.jpa.annotations.IndexColumn.Store;
import cn.ilikes.tools.hbase.jpa.annotations.IndexColumn.TermVector;
import cn.ilikes.tools.hbase.jpa.clients.nodes.Node;
import cn.ilikes.tools.hbase.jpa.clients.nodes.Node.NodeLink;
import cn.ilikes.tools.hbase.jpa.indexs.Indexer;
import cn.ilikes.tools.hbase.jpa.metadatas.IEntityMetaData;
import cn.ilikes.tools.hbase.jpa.metadatas.elements.EntityFields;
import cn.ilikes.tools.hbase.jpa.metadatas.elements.Relation;
import cn.ilikes.tools.logs.Loggerfactory;
import cn.ilikes.tools.untils.HBaseUtils;
import cn.ilikes.tools.untils.PropertyAccessorHelper;

public class LuceneEntityFieldsToDocuments {

	private static Logger logger = Loggerfactory.instance(LuceneIndexer.class);

	public void addEntityFieldsToDocumentst(Document document, Node node) throws LuceneIndexingException {
		IEntityMetaData entityMetaData = Node.getEntityMetaData(node);
		//		String indexName = entityMetaData.getEntityIndex().getIndexName();

		for (EntityFields entityFields : entityMetaData.getEntityFields().values()) {
			if (Loggerfactory.isdebug(logger))
				
			//			if (Loggerfactory.isdebug(logger))
			//				Loggerfactory.debug(logger, "===========================> " + entityFields.isIndexable() + "  " + entityFields.getField().getName());
			if (entityFields.isIndexable()) {
				
				if (entityFields.getEntityFieldsType().equals(EntityFields.EntityFieldsType.RealocalKey)) {
					NodeLink nodeLink = node.getNodeLink().get(entityFields);
					addRealocalKeyEntityFieldsToDocuments(document, Node.getEntity(node), entityMetaData, entityFields, nodeLink);
				} else if (entityFields.getEntityFieldsType().equals(EntityFields.EntityFieldsType.RoreignKey)) {
					NodeLink nodeLink = node.getNodeLink().get(entityFields);
					addRoreignKeyEntityFieldsToDocuments(document, Node.getEntity(node), entityMetaData, entityFields, nodeLink);
				}

			}
		}
	}

	private String createLuceneFieldsName(String indexName, String columnName) {
		int index = columnName.indexOf(SysConfigs.hbase_column_family_qualifier);
		String family = HBaseUtils.getfamily(columnName, index);
		String qualifier = HBaseUtils.getQualifier(columnName, index);
		String luceneFieldsName = LuceneQueryUtils.createLuceneFieldsName(indexName, family, qualifier);
		return luceneFieldsName;
	}

	private void addFieldDocument(Document document, EntityFields entityFields, String luceneFieldsName, Object lucenefieldValue) {

		Field.Store luStore = swtichLuFieldStore(entityFields.getIndexField().getStore());
		Field.Index luIndex = swtichLuFieldIndex(entityFields.getIndexField().getIndex());

		//		if (entityFields.getField().getType().equals(String.class))
		{
			Field.TermVector luTermVector = swtichLuFieldTermVector(entityFields.getIndexField().getTermVector());
			Field luceneField = new Field(luceneFieldsName, lucenefieldValue.toString(), luStore, luIndex, luTermVector);
			document.add(luceneField);
		}
		//		else if (entityFields.getField().getType().equals(Integer.class)) {
		//
		//			NumericField luceneField = new NumericField(luceneFieldsName, luStore, true);
		//			luceneField.setIntValue((Integer) lucenefieldValue);
		//			document.add(luceneField);
		//		} else if (entityFields.getField().getType().equals(Integer.class)) {
		//
		//			NumericField luceneField = new NumericField(luceneFieldsName, luStore, true);
		//			luceneField.setIntValue((Integer) lucenefieldValue);
		//			document.add(luceneField);
		//		} else if (entityFields.getField().getType().equals(Integer.class)) {
		//
		//			NumericField luceneField = new NumericField(luceneFieldsName, luStore, true);
		//			luceneField.setIntValue((Integer) lucenefieldValue);
		//			document.add(luceneField);
		//		}else
		//			throw new LuceneIndexingException("not find  : "+entityFields.getField().getType()+"! this is not work !");

	}

	/**
	 * 
	 * @param document
	 * @param entity
	 * @param entityMetaData
	 * @param entityFields
	 * @param nodeLink
	 *                  当 null 没有 关系的EntityFields
	 */
	private void addRealocalKeyEntityFieldsToDocuments(Document document, Object entity, IEntityMetaData entityMetaData, EntityFields entityFields, NodeLink nodeLink) {
		if(entityFields.getjPAField()==null) return;
		String indexName = entityMetaData.getEntityIndex().getIndexName();
		if (entityFields.getjPAField().isRelation()) {//有关系

			Relation relation = entityFields.getjPAField().getRelation();
			Class<?> targetEntity = relation.getTargetEntity();
			IEntityMetaData targetEntityMetaData = entityMetaData.getJPAHbasePersistenUnitEnv().getEntityMetaDataFactory().selectIEntityMetaData(targetEntity);
			EntityFields targetEntityFieldsId = targetEntityMetaData.getEntityId();
			String columnName = relation.getColumnName();
			String luceneFieldsName = createLuceneFieldsName(indexName, columnName);
			Object lucenefieldValue = Indexer.index_fields_null;
			//有节点链接类型
			if (nodeLink != Node.NULL_NODE_LINK) {

				Object value = nodeLink.getTargetObject();
				if (value != null) {
					lucenefieldValue = PropertyAccessorHelper.getObject(value, targetEntityFieldsId.getField());
				} else {
					lucenefieldValue = Indexer.index_fields_null;
				}
			} else//
			{
				lucenefieldValue = Indexer.index_fields_null;
			}
			if (Loggerfactory.isdebug(logger))
				Loggerfactory.debug(logger, "Luncene  Realocal Key   Index  column name  :  " + luceneFieldsName + "  value : " + lucenefieldValue);
			addFieldDocument(document, entityFields, luceneFieldsName, lucenefieldValue);
		} else {//无关系

			Object lucenefieldValue = PropertyAccessorHelper.getObject(entity, entityFields.getField());
//			Loggerfactory.debug(logger, " ==<>== " + entityFields.getField().getName() + "     " + entityFields.isIndexable()+"    "+entityFields.getEntityFieldsType().name()+" xxx "+lucenefieldValue);
			if (lucenefieldValue == null)
				return;
			String columnName = entityFields.getjPAField().getColumnName();
			String luceneFieldsName = createLuceneFieldsName(indexName, columnName);
			if (Loggerfactory.isdebug(logger))
				Loggerfactory.debug(logger, "Luncene  entity  field  Index column  name  :  " + luceneFieldsName + "  value : " + lucenefieldValue
						+ "            entityFields  " + entityFields.getFieldName());
			addFieldDocument(document, entityFields, luceneFieldsName, lucenefieldValue);
		}

	}

	private void addRoreignKeyEntityFieldsToDocuments(Document document, Object entity, IEntityMetaData entityMetaData, EntityFields entityFields, NodeLink nodeLink) {
		String indexName = entityMetaData.getEntityIndex().getIndexName();

		Relation relation = entityFields.getjPAField().getRelation();
		Class<?> targetEntity = relation.getTargetEntity();

		IEntityMetaData targetEntityMetaData = entityMetaData.getJPAHbasePersistenUnitEnv().getEntityMetaDataFactory().selectIEntityMetaData(targetEntity);

		String columnName = relation.getColumnName();
		String luceneFieldsName = createLuceneFieldsName(indexName, columnName);

		Object lucenefieldValue = PropertyAccessorHelper.getObject(nodeLink.getTargetObject(), targetEntityMetaData.getEntityId().getField());
		if(lucenefieldValue ==null) return;

		if (Loggerfactory.isdebug(logger))
			Loggerfactory.debug(logger, "Luncene  Roreign Key   Index  column name  :  " + luceneFieldsName + "  value : " + lucenefieldValue);
		addFieldDocument(document, entityFields, luceneFieldsName, lucenefieldValue);
	}

	private Field.Index swtichLuFieldIndex(Index index) {
		Field.Index luIndex;
		switch (index) {
		case analyzed:
			luIndex = Field.Index.ANALYZED;
			break;
		case not_analyzed:
			luIndex = Field.Index.NOT_ANALYZED;
			break;

		default:
			luIndex = Field.Index.NO;
			break;
		}
		if (Loggerfactory.isdebug(logger))
			Loggerfactory.debug(logger, "Luncene swtich LuField  Index  column name  :  " + index + "  luIndex : " + luIndex);
		return luIndex;
	}

	private Field.Store swtichLuFieldStore(Store store) {
		Field.Store luStore;
		switch (store) {
		case yes:
			luStore = Field.Store.YES;
			break;
		default:
			luStore = Field.Store.NO;
			break;
		}
		return luStore;
	}

	private Field.TermVector swtichLuFieldTermVector(TermVector termVector) {
		Field.TermVector luTermVector;
		//yes, no, with_posttions, with_offsets, with_posttions_offsets
		switch (termVector) {
		case yes:
			luTermVector = Field.TermVector.YES;
			break;
		case with_posttions:
			luTermVector = Field.TermVector.WITH_POSITIONS;
			break;
		case with_offsets:
			luTermVector = Field.TermVector.WITH_OFFSETS;
			break;
		case with_posttions_offsets:
			luTermVector = Field.TermVector.WITH_POSITIONS_OFFSETS;
			break;

		default:
			luTermVector = Field.TermVector.NO;
			break;
		}
		return luTermVector;
	}

	//	private void addRealocalKeyEntityFieldsToDocuments(Document document, Object entity, IEntityMetaData metadata, EntityFields entityFields, NodeLink nodeLink) throws LuceneIndexingException {
	//		String indexName = metadata.getEntityIndex().getIndexName();
	//		java.lang.reflect.Field field = entityFields.getField();
	//		String colName = field.getName();
	//		try {
	//			Object fieldValue = PropertyAccessorHelper.fieldValue(entity, field);
	//			if (fieldValue == null) {
	//				Loggerfactory.warn(logger, "add field to documents  lucene field value not find   : " + field.getName());
	//			} else {
	//				String luceneFieldsName = LuceneQueryUtils.createLuceneFieldsName(indexName, colName);
	//				Field.Store luStore = swtichLuFieldStore(entityFields.getIndexField().getStore());
	//				Field.Index luIndex = swtichLuFieldIndex(entityFields.getIndexField().getIndex());
	//				Field.TermVector luTermVector = swtichLuFieldTermVector(entityFields.getIndexField().getTermVector());
	//				JPAField jpafield = entityFields.getjPAField();
	//				if (!jpafield.isRelation())//field
	//				{
	//					Field luceneField = new Field(luceneFieldsName, fieldValue.toString(), luStore, luIndex, luTermVector);
	//					document.add(luceneField);
	//					if (Loggerfactory.isdebug(logger))
	//						Loggerfactory.debug(logger, "add field to documents  lucene field : " + luceneFieldsName + " value : " + fieldValue.toString()
	//								+ "  property index " + entityFields.getIndexField().toString());
	//				} else {//关系
	//					String puName = metadata.getPuName();
	//					Object id = PropertyAccessorHelper.getJPAEntityId(puName, fieldValue);
	//					Field luceneField = new Field(luceneFieldsName, id.toString(), luStore, luIndex, luTermVector);
	//					document.add(luceneField);
	//					if (Loggerfactory.isdebug(logger))
	//						Loggerfactory.debug(logger, "add field to documents  lucene field : " + luceneFieldsName + " value : " + id.toString()
	//								+ "  property index " + entityFields.getIndexField().toString());
	//
	//				}
	//
	//			}
	//		} catch (Exception e) {
	//			Loggerfactory.error(logger, "Error in accessing field, Caused by:" + e.getMessage());
	//			throw new LuceneIndexingException("Error in accessing field:" + field.getName(), e);
	//		}
	//	}

}
